package com.jtcoding.chat.service.impl;

import com.jtcoding.chat.handler.ChatServerHandler;
import com.jtcoding.chat.service.NettyService;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
 * @Author jason.tang
 * @Date 2019/02/6 14:18
 * @Desc
 */
@Service("nettyService")
public class NettyServiceImpl implements NettyService {

    private ServerBootstrap bootstrap;
    private NioEventLoopGroup bossGrp;
    private NioEventLoopGroup workerGrp;

    private static Map<Integer, Channel> userChannelMap;

    @PostConstruct
    public void autoStartup() {
        userChannelMap = new HashMap<>();

        bootstrap = new ServerBootstrap();
        bossGrp = new NioEventLoopGroup();
        workerGrp = new NioEventLoopGroup();

        bootstrap.group(bossGrp, workerGrp)
                .channel(NioServerSocketChannel.class)
                .childHandler(new ChannelInitializer<NioSocketChannel>() {
                    protected void initChannel(NioSocketChannel socketChannel) throws Exception {
                        /** 指定连接数据读写逻辑 **/
                        // 1. 获取与这条连接相关的逻辑处理链（责任链模式）
                        ChannelPipeline pipeline = socketChannel.pipeline();
                        // 2. 添加一个逻辑处理器（负责读取客户端写来的数据）
                        pipeline.addLast(new ChatServerHandler());
                    }
                });
        bootstrap.bind("localhost",9001);
    }


    @Override
    public void putUserChannel(Integer userNum, Channel channel) {
        userChannelMap.put(userNum, channel);
    }

    @Override
    public void removeUserChannelByNum(Integer userNum) {
        userChannelMap.remove(userNum);
    }

    @Override
    public void removeUserChannel(Channel channel) {
        for (Map.Entry<Integer, Channel> entry : userChannelMap.entrySet()) {
            if (Objects.equals(entry.getValue(), channel)) {
                userChannelMap.remove(entry.getKey());
                break;
            }
        }
    }

    @Override
    public Channel getChannelByNum(Integer userNum) {
        return userChannelMap.get(userNum);
    }
}
